#! /usr/bin/env python
import pygtk
from simpleOSC import *
pygtk.require('2.0')
import gtk, gobject, cairo
import math
import argparse

# Dummy Screen
# This program will provide a dummy screen for data visualization, which will be controlled by OSC messages.
# When it begins executing, the only message that it will respond to is '/create'.
# Data for that message should be a string containing the name of the message related to another object, as:
# sendOSCMsg("/create", ["/someObject"]) 
# (list form is important!)
#
# After that, every time the server receives the message "/someObject" it will update its properties to the
# data sent in the message. 
# This data should be a list of 6 numbers:
# x and y positions of the object - 0 to 1, where 1 is the full width or height of the canvas
# z position, which is the size of the object - 0 to 1, where 1 is the full width or height of the canvas
# r, g, b color descriptors of the object (or just set them to 0, 0, 0 if you want it all black)
# which means something like this:
# sendOSCMsg("/someObject", [.7, .2, .1, 0, 1, 1])
#
# Code written by Tiago F. Tavares
# Highly based on the Cairo Tutorial for PyGTK by Michael Urman - http://www.tortall.net/mu/wiki/PyGTKCairoTutorial
#
# Maybe I will add some more stuff, if I fell like...
# 
# You can use this both as a library and as a standalone application.

GlobalWidget = None; # It's ugly to use global variables. Doesn't matter, I do a lot of ugly stuff...

# Create a GTK+ widget on which we will draw using Cairo
class Screen(gtk.DrawingArea):

	Events = {};
	lastEvent = None;

	# Draw in response to an expose-event
	__gsignals__ = { "expose-event": "override" }

	def setEvent(self, address, data, update=1):
#		print "Setting event ", address, " to ", data
		self.Events[address] = data;
		
		if update==1:
			self.do_expose_event(self.lastEvent)

	def getData(self, address):
		return self.Events[address];

	# Handle the expose-event by drawing
	def do_expose_event(self, event):
		# Create the cairo context
		cr = self.window.cairo_create()
		# Restrict Cairo to the exposed area; avoid extra work
		cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
		cr.clip()

		# save the context
		self.lastEvent = event;

		self.draw(cr, *self.window.get_size())

	def draw(self, cr, width, height): 	# Every time the 'draw' routine is called, it redraws everything.
																			#That's ok, we will probably not do that very often...
		self.erase(cr, width, height)
		for e in self.Events:
			cr.set_source_rgb(self.Events[e][3], self.Events[e][4], self.Events[e][5])
			cr.rectangle(int(self.Events[e][0]*width), int(self.Events[e][1]*height), int(self.Events[e][2]*width), int(self.Events[e][2]*height))
			cr.fill()

	def erase(self, cr, width, height):
		# Erase means: fill the background with white
		cr.set_source_rgb(1, 1, 1)
		cr.rectangle(0, 0, width, height)
		cr.fill()

def newObject(addr, tags, data, source):
	setOSCHandler(data[0], setEvent)
	print "Added OSC handler for object: ", data[0]
	reportOSCHandlers()

def setEvent(addr, tags, data, source, etc=0):
	print GlobalWidget
	print etc
	GlobalWidget.setEvent(addr, data)

# GTK mumbo-jumbo to show the widget in a window and quit when it's closed
# (and run the OSC server at the same time!)
def start(Widget, IP=None, port=None):
	window = gtk.Window()
	window.connect("delete-event", gtk.main_quit)
	widget = Widget()
	widget.show()
	GlobalWidget = widget
	window.add(widget)
	window.present()
	for i in range(5):
		gtk.main_iteration(False)

	print "Window should be showing by now..."
	return widget

def run(Widget, IP=None, port=None):
	global GlobalWidget
	try:
		if IP != None:
			initOSCServer(IP, port, 1)
			setOSCHandler("/create", newObject)
			reportOSCHandlers()
			print "Server up and running!"
			print "Using interface: ", IP, " on port ", port

		while(1):
			gtk.main_iteration(False)

	except KeyboardInterrupt:
		pass;

	if IP != None:
		print "\nClosing OSCServer."
		print "Waiting for Server-thread to finish"
		closeOSC()

	print "Done"

if __name__ == "__main__":
	parser = argparse.ArgumentParser(description='pyGTK+ based, OSC-controlled data display device')
	parser.add_argument('--IP', '-i', metavar='IP', default='127.0.0.1', type=str, help='IP interface to use (default: 127.0.0.1)')
	parser.add_argument('--Port', '-p', metavar='Port', default=9001, type=int, help='Port to be used (default: 9001)') # Our default is OVER 9000!
	args = parser.parse_args()
	print "Trying to open server using interface ", args.IP, " on port ", args.Port

	start(Screen, args.IP, args.Port)
	run(Screen, args.IP, args.Port)

